/**
  ******************************************************************************
  * @file    main.c
  * @author  Milandr Application Team
  * @version V2.1.0
  * @date    22/06/2023
  * @brief   Main program body.
  ******************************************************************************
  * <br><br>
  *
  * THE PRESENT FIRMWARE IS FOR GUIDANCE ONLY. IT AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING MILANDR'S PRODUCTS IN ORDER TO FACILITATE
  * THE USE AND SAVE TIME. MILANDR SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES RESULTING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR A USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2026 Milandr </center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "MDR32F9Qx_config.h"
#include "MDR32F9Qx_rst_clk.h"
#include "MDR32F9Qx_eeprom.h"
#include "MDR32F9Qx_bkp.h"
#include "MDR32F9Qx_port.h"
#include "MDR32F9Qx_utils.h"
#include "MDR32F9Qx_audio.h"

/** @addtogroup __MDR32Fx_StdPeriph_Examples MDR32Fx StdPeriph Examples
  * @{
  */

/** @addtogroup __MDR1986VE3_EVAL MDR1986VE3 Evaluation Board
  * @{
  */

/** @addtogroup AUDIO_IP_VE3 AUDIO_IP
 *  @{
 */

/* Private macro -------------------------------------------------------------*/
#if defined (_USE_DEBUG_UART_)
    #define DEBUG_PRINTF(...) printf(__VA_ARGS__)
#else
    #define DEBUG_PRINTF(...)
#endif /* #if defined _USE_DEBUG_UART_ */

/* Private variables ---------------------------------------------------------*/
static PORT_InitTypeDef PORT_InitStructure;
volatile uint32_t audio_data = 0;

/* Private function prototypes -----------------------------------------------*/
void ClockConfigure(void);

/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Audio codec interrupt handler.
  * @param  None
  * @retval None
  */
void AudioCodec_IRQHandler(void)
{
    if (AUDIO_IP_GetITStatus(AUDIO_IP_FLAG_ADCNS))
    {
        audio_data = AUDIO_IP_ReceiveData();
        AUDIO_IP_SendData(audio_data);
    }
}

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
#if defined (_USE_DEBUG_UART_)
    ErrorStatus Status;
#endif
    AUDIO_IP_InitTypeDef AUDIO_IP_InitStruct;

    /* Configure CPU clock */
    ClockConfigure();

    SystemCoreClockUpdate();

#if defined (_USE_DEBUG_UART_)
    Status = STDIO_Init();
    if (Status == ERROR)
    {
        while (1) { }
    }
#endif /* #if defined (_USE_DEBUG_UART_) */

    /* Enable peripheral clocks */
    RST_CLK_AUCclkDeInit();
    RST_CLK_AUCclkSelection(RST_CLK_AUCclkHSE_2_C1);
    RST_CLK_AUCclkPrescaler(RST_CLK_AUCclkDIV1);
    RST_CLK_AUCclkCMD(ENABLE);
    RST_CLK_PCLK2cmd(RST_CLK_PCLK2_AUDIO_IP, ENABLE);

    /* AUDIO_IP Configuration */
    /* Reset all settings */
    AUDIO_IP_DeInit();
    AUDIO_IP_StructInit(&AUDIO_IP_InitStruct);

    /* AUDIO_IP ADC Configuration */
    AUDIO_IP_InitStruct.ADCAnalogInput           = AUDIO_IP_ANALOG_INPUT_SOURCE_MICIN_INT;
    AUDIO_IP_InitStruct.ADCInputControl          = ENABLE;
    /* AUDIO_IP DAC Configuration */
    AUDIO_IP_InitStruct.DACBIASOffsetSchemeState = ENABLE;
    AUDIO_IP_InitStruct.DACAnalogState           = ENABLE;
    AUDIO_IP_InitStruct.DACSideToneLoopBack      = AUDIO_IP_DAC_SIDE_TONE_LOOP_BACK_MUTE;
    AUDIO_IP_InitStruct.DACOutputAmplifier       = ENABLE;
    AUDIO_IP_InitStruct.DACState                 = ENABLE;
    AUDIO_IP_Init(&AUDIO_IP_InitStruct);

    /* Enable AUDIO_IP ADCNSM interrupt  */
    AUDIO_IP_ITConfig(AUDIO_IP_IT_ADCNSM, ENABLE);
    /* Enable global AUDIO_IP IRQ */
    NVIC_EnableIRQ(AUDIO_IP_IRQn);

    /* Enable AUDIO_IP ADC */
    AUDIO_IP_ADCCmd(ENABLE);
    /* Enable AUDIO_DAC ADC */
    AUDIO_IP_DACCmd(ENABLE);

    /* Infinite loop */
    while(1) {}
}

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Configure CPU clock.
  * @param  None
  * @retval None
  */
void ClockConfigure(void)
{
    RST_CLK_DeInit();

    /* Enable HSE (High Speed External) clock */
    RST_CLK_HSEconfig(RST_CLK_HSE_ON);
    while(RST_CLK_HSEstatus() == ERROR) {}

    /* Configures the CPU_PLL clock source */
    RST_CLK_CPU_PLLconfig(RST_CLK_CPU_PLLsrcHSEdiv1, RST_CLK_CPU_PLLmul10);
    /* Enables the CPU_PLL */
    RST_CLK_CPU_PLLcmd(ENABLE);
    while(RST_CLK_CPU_PLLstatus() == ERROR) {}

    /* Select the CPU_PLL output as input for CPU_C3_SEL */
    RST_CLK_CPU_PLLuse(ENABLE);
    /* Set CPUClk Prescaler */
    RST_CLK_CPUclkPrescaler(RST_CLK_CPUclkDIV1);

    /* Enables the RST_CLK_PCLK_EEPROM */
    RST_CLK_PCLKcmd(RST_CLK_PCLK_EEPROM, ENABLE);
    /* Sets the code latency value */
    EEPROM_SetLatency(EEPROM_Latency_3);

    /* Setup internal DUcc voltage regulator work mode based on clock frequency */
    BKP_DUccMode(BKP_DUcc_upto_80MHz);

    /* Select the CPU clock source */
    RST_CLK_CPUclkSelection(RST_CLK_CPUclkCPU_C3);
}

/**
  * @brief  Reports the source file name, the source line number
  *         and expression text (if USE_ASSERT_INFO == 2) where
  *         the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @param  expr:
  * @retval None
  */
#if (USE_ASSERT_INFO == 1)
void assert_failed(uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the source file name and line number.
       Ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while(1) {}
}
#elif (USE_ASSERT_INFO == 2)
void assert_failed(uint8_t* file, uint32_t line, const uint8_t* expr)
{
    /* User can add his own implementation to report the source file name, line number and
       expression text.
       Ex: printf("Wrong parameters value (%s): file %s on line %d\r\n", expr, file, line) */

    /* Infinite loop */
    while(1) {}
}
#endif /* USE_ASSERT_INFO */

/** @} */ /* End of group AUDIO_IP_VE3 */

/** @} */ /* End of group MDR1986VE3_Complexity_Evaluation_Board */

/** @} */ /* End of group __MDR32Fx_StdPeriph_Examples */

/******************* (C) COPYRIGHT 2026 Milandr ********************************
*
* END OF FILE main.c */

